/**********************************************************************
 Copyright (C) 2010 Teppo Eeva

 This file is part of Arithmetic Game.
 For more information, see <http://code.google.com/p/arithmetic-game/>

 Arithmetic Game is free software: you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation, either version 3 of the License, or
 (at your option) any later version.

 Arithmetic Game is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.

 You should have received a copy of the GNU General Public License
 along with Arithmetic Game.  If not, see <http://www.gnu.org/licenses/>.
 **********************************************************************/

#include "highscoremanager.h"
#include <QDebug>
#include <QInputDialog>
#include <QSettings>
#include <QDialog>
#include <QTableView>
#include <QVBoxLayout>
#include <QPushButton>
#include <QStandardItemModel>
#include <QStandardItem>
#include <QHeaderView>
#include <QScrollBar>
#include <QMessageBox>


const int KVisibleHighScores = 5;

HighScoreManager::HighScoreManager()
{

}

HighScoreManager::~HighScoreManager()
{
    storeHighScores(m_easyScoreList, Easy);
    storeHighScores(m_moderateScoreList, Moderate);
    storeHighScores(m_hardScoreList, Hard);
}

void HighScoreManager::loadHighStores(const QString storeName)
{
    m_storeName = storeName;

    restoreHighScores(m_easyScoreList, Easy);
    if (m_easyScoreList.isEmpty())
        initHighScores(m_easyScoreList);

    restoreHighScores(m_moderateScoreList, Moderate);
    if (m_moderateScoreList.isEmpty())
        initHighScores(m_moderateScoreList);

    restoreHighScores(m_hardScoreList, Hard);
    if (m_hardScoreList.isEmpty())
        initHighScores(m_hardScoreList);
}


void HighScoreManager::suggestNewHighScore(HighScoreItem& newItem, ArithDiffLevel diffLevel)
{
    qDebug() << "addNewScore - score:" << newItem.m_score << "level:" << newItem.m_level;

    if (newItem.m_score <= 0)
    {
        return;
    }
    bool handled = false;

    QList<HighScoreItem>& m_highScoreList = getHighScoreList( diffLevel );
    int j = 5;
    QListIterator<HighScoreItem> i(m_highScoreList);
    while(!handled && j>0 && i.hasNext())
    {
        const HighScoreItem& item = i.next();
        int index = m_highScoreList.indexOf(item);
        if (index > KVisibleHighScores)
        {
            qDebug() << "Didn't reach high score limits' " << newItem.m_score;
            handled = true;
        }
        else if( newItem.m_score > item.m_score )
        {
            qDebug() << "Reached to high score limits' " << newItem.m_score;
            if(queryName(m_latestName))
            {
                newItem.m_name = m_latestName;
                newItem.generateUniqueHash();
                m_highScoreList.insert(index, newItem);
                qDebug() << "added " << m_latestName << " to high score table, index = " << index;
            }
        handled = true;
        j--;
        }
    }

    if (!handled && m_highScoreList.count() < 5 )
        {
        if(queryName(m_latestName))
        {
            newItem.m_name = m_latestName;
            m_highScoreList.append(newItem);
            qDebug() << "added " << m_latestName << " to high score table";
        }
    }
}

bool HighScoreManager::queryName(QString name)
{
    bool accepted = false;
    m_latestName = QInputDialog::getText(NULL, tr("New high score"), tr("Enter your name:"), QLineEdit::Normal, m_latestName, &accepted);

    if (!accepted)
    {
        qDebug() << "User cancel high score query";
    }
    return accepted;
}

void HighScoreManager::initHighScores(QList<HighScoreItem>& highScoreList)
{
    qDebug() << "Initializing highscore list...";
    HighScoreItem item1( QString("Mikki Hiiri"), 30, 3 );
    highScoreList.append(item1);

    HighScoreItem item2( QString("Aku Ankka"), 20, 2 );
    highScoreList.append(item2);

    HighScoreItem item3( QString("Hessu Hopo"), 10, 1 );
    highScoreList.append(item3);
}

void HighScoreManager::restoreHighScores(QList<HighScoreItem>& highScoreList, ArithDiffLevel diffLevel)
{
    qDebug() << "Restore highscores from " << m_storeName;
    QSettings settings(m_storeName);

    int count = settings.beginReadArray(QString("highscorelist%1").arg(diffLevel));

    for(int i=0; i<count; ++i)
    {
        settings.setArrayIndex(i);
        HighScoreItem item(  settings.value("name").toString(), settings.value("score").toInt(), settings.value("level").toInt(), settings.value("uniquehash").toByteArray() );
        highScoreList.append(item);
        qDebug() << "restored: " << item;
    }
    settings.endArray();
}

void HighScoreManager::storeHighScores(const QList<HighScoreItem>& highScoreList, ArithDiffLevel diffLevel)
{
    qDebug() << "Store highscores to " << m_storeName;
    QSettings settings(m_storeName);

    QListIterator<HighScoreItem> i(highScoreList);
    settings.beginWriteArray(QString("highscorelist%1").arg(diffLevel));

    int index = 0;
    while(i.hasNext())
    {
        const HighScoreItem& item = i.next();
        qDebug() << "storing: " << item;
        settings.setArrayIndex(index);
        settings.setValue("score", item.m_score);
        settings.setValue("name", item.m_name);
        settings.setValue("level", item.m_level);
        settings.setValue("uniquehash", item.m_uniqueHash);
        index++;
    }
    settings.endArray();
}

void HighScoreManager::resetHighScores()
{
    qDebug() << "Reset high scores";

    m_easyScoreList.clear();
    initHighScores(m_easyScoreList);
    storeHighScores(m_easyScoreList, Easy);

    m_moderateScoreList.clear();
    initHighScores(m_moderateScoreList);
    storeHighScores(m_moderateScoreList, Moderate);

    m_hardScoreList.clear();
    initHighScores(m_hardScoreList);
    storeHighScores(m_hardScoreList, Hard);
}

QStandardItemModel* HighScoreManager::getHighScoreModel(ArithDiffLevel diffLevel)
{
    const QList<HighScoreItem>& m_highScoreList = getHighScoreList( diffLevel );

    QStandardItemModel* model = new QStandardItemModel();
    model->setHorizontalHeaderItem(0, new QStandardItem(tr("score")));
    model->setHorizontalHeaderItem(1, new QStandardItem(tr("name")));
    model->setHorizontalHeaderItem(2, new QStandardItem(tr("level")));

    //populate model
    QListIterator<HighScoreItem> i(m_highScoreList);
    int index = 0;

    while(i.hasNext() && index < KVisibleHighScores)
    {
        const HighScoreItem& item = i.next();
        model->setItem(index,0, new QStandardItem(QString::number(item.m_score)));
        model->setItem(index,1, new QStandardItem(item.m_name));
        model->setItem(index,2, new QStandardItem(QString::number(item.m_level)));
        index++;
    }
    return model;
}


QList<HighScoreItem>& HighScoreManager::getHighScoreList(ArithDiffLevel diffLevel)
{
    QList<HighScoreItem>* m_highScoreList;

    switch(diffLevel)
    {
        case Easy:
            m_highScoreList = &m_easyScoreList;
            break;
    case Moderate:
            m_highScoreList =  &m_moderateScoreList;
            break;
        case Hard:
        default:
            m_highScoreList = &m_hardScoreList;
            break;
    }
    return *m_highScoreList;
}
//end of file

